package org.changs.nav;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v7.app.NotificationCompat;
import android.widget.Toast;

import com.google.gson.JsonObject;

import org.changs.aplug.utils.EmptyUtils;
import org.changs.aplug.utils.FileUtils;
import org.changs.aplug.utils.JsonUtils;
import org.changs.s3.common.tools.NavTools;
import org.changs.servlet.AplugClient;
import org.changs.servlet.CommunicationConfig;
import org.changs.servlet.IOUtils;
import org.changs.servlet.ReceiveFile;
import org.changs.servlet.ReceiveFileCallback;
import org.changs.servlet.message.VMapMessage;

import java.io.File;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.schedulers.Schedulers;
import timber.log.Timber;

/**
 * Created by yincs on 2017/9/14.
 */

public class NavService extends Service {

    private NotificationManager mNotificationManager;

    private boolean isUpdating;
    private int updateCount;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Timber.d("onStartCommand() called with: intent = [" + intent + "], flags = [" + flags + "], startId = [" + startId + "]");
        final String action = intent.getAction();
        if (IOUtils.Action.SYM_MAP_DATA.equals(action)) {
            symMapData(intent);
        }
        return START_STICKY_COMPATIBILITY;
    }


    private void symMapData(Intent intent) {
        if (isUpdating) return;
        String remoteIp = intent.getStringExtra(IOUtils.EXTRA_REMOTE_IP);
        if (remoteIp == null) {
            Timber.d("symMapData: remoteIp == null");
            return;
        }
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        final String data = intent.getStringExtra(IOUtils.EXTRA_DATA);
        Timber.d("data = " + data);
        Timber.d("onReceive: %s", Thread.currentThread().getName());

        if (EmptyUtils.isEmpty(remoteIp)) {
            Toast.makeText(this, "连接手机失败,无法更新地图", Toast.LENGTH_SHORT).show();
            return;
        }
        isUpdating = true;
        List<VMapMessage> vMapMessages = JsonUtils.fromJsonList(data, VMapMessage.class);
        Observable.fromIterable(vMapMessages)
                .filter(this::isNeedUpdate)
                .doOnNext(vMapMessage -> {
                    updateCount++;
                    final JsonObject message = new JsonObject();
                    message.addProperty(IOUtils.EXTRA_FILE_NAME, vMapMessage.getFile().getTitle());
                    AplugClient.receive(remoteIp, CommunicationConfig.PHONE_SERVER_PORT, message,
                            parseReceiveFile(vMapMessage),
                            new MyReceiveFileCallback(vMapMessage));
                })
                .doOnComplete(() -> {
                    JsonObject request = new JsonObject();
                    request.addProperty(IOUtils.EXTRA_ACTION, IOUtils.Event.SYNC_MAP_DONE);
                    AplugClient.send(remoteIp, CommunicationConfig.PHONE_SERVER_PORT, request.toString());
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnComplete(() -> {
                    Timber.d("onReceive: doOnComplete %s", Thread.currentThread().getName());
                    isUpdating = false;
                    if (updateCount != 0) {
                        Toast.makeText(this, "地图已成功更新", Toast.LENGTH_SHORT).show();
                        updateCount = 0;
                    }
                    stopSelf();
                })
                .subscribe();
    }

    private ReceiveFile parseReceiveFile(VMapMessage remoteVMap) {
        final VMapMessage.FileBean fileBean = remoteVMap.getFile();
        final String pinyin = fileBean.getPinyin();
        File localFile2Save = getLocalMapDatFile(fileBean.getVMapFileNames());
        Timber.d("localFile2Save = " + localFile2Save);
        String remoteFilePath = fileBean.getFileName()
                .replace(String.format("VMAP2/%s.zip.tmp", pinyin), "map/" +
                        fileBean.getVMapFileNames().replace(";", ""));
        Timber.d("remoteFilePath = " + remoteFilePath);
        return new ReceiveFile(remoteFilePath, remoteVMap.getFileSize(), localFile2Save);
    }

    private boolean isNeedUpdate(@NonNull VMapMessage remoteVMap) {
        final String pinyin = remoteVMap.getFile().getPinyin();
        final File file = getLocalMapVMAP2CityFile(pinyin);
        if (!file.exists())
            return true;
        VMapMessage localVMap;
        try {
            final String local = FileUtils.readFile2String(file, null);
            localVMap = JsonUtils.parseObject(local, VMapMessage.class);
        } catch (Exception e) {
            e.printStackTrace();
            return true;
        }
        final String remoteVersion = remoteVMap.getFile().getVersion();
        final String localVersion = localVMap.getFile().getVersion();
        return remoteVersion.compareTo(localVersion) > 0;
    }


    private File getLocalMapVMAP2CityFile(String pinyin) {
        return new File(NavTools.getMapRootDir(this), String.format("data/VMAP2/%s.zip.tmp.dt", pinyin));
    }

    private File getLocalMapDatFile(String vMapFileNames) {
        return new File(NavTools.getMapRootDir(this), String.format("data/map/%s", vMapFileNames.replace(";", "")));
    }

    private void showReceiveMapNotify(String cityName) {
        final Notification notification = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("离线地图同步中...")
                .setContentText("正在更新" + cityName)
                .setContentInfo("S3")
                .setDefaults(getNotificationSettings())
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .build();
        mNotificationManager.notify(2, notification);
    }

    public int getNotificationSettings() {
        return NotificationCompat.DEFAULT_SOUND | NotificationCompat.DEFAULT_VIBRATE | NotificationCompat.DEFAULT_LIGHTS;
    }

    private class MyReceiveFileCallback implements ReceiveFileCallback {
        private final VMapMessage message;

        private MyReceiveFileCallback(VMapMessage message) {
            this.message = message;
        }

        @Override
        public void onError(int i, String msg) {
            Timber.d("onError() called with: " + "i = [" + i + "], msg = [" + msg + "]");
        }

        @Override
        public void onStart() {
            showReceiveMapNotify(message.getFile().getTitle());
        }

        @Override
        public void onProgress(int currentPercent) {
            Timber.d("onProgress() called with: " + "currentPercent = [" + currentPercent + "]");
        }

        @Override
        public void onSuccess() {
            Timber.d("下载成功： message.getFile().getFileName() = " + message.getFile().getFileName());
            final File vmap2CityFile = getLocalMapVMAP2CityFile(message.getFile().getPinyin());
            FileUtils.writeFileFromString(vmap2CityFile, JsonUtils.stringify(message), false);
        }

        @Override
        public void onComplete() {
            Timber.d("onComplete() called with: " + "");
            mNotificationManager.cancel(2);
        }
    }
}
